<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 1.5.3">
<title>Contracts on the Producer Side 2.1.3.BUILD-SNAPSHOT</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
<style>
/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */
/* Remove comment around @import statement below when using as a custom stylesheet */
/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/
article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}
audio,canvas,video{display:inline-block}
audio:not([controls]){display:none;height:0}
[hidden],template{display:none}
script{display:none!important}
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
body{margin:0}
a{background:transparent}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
abbr[title]{border-bottom:1px dotted}
b,strong{font-weight:bold}
dfn{font-style:italic}
hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:"\201C" "\201D" "\2018" "\2019"}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}
input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}
input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,*:before,*:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
body{-webkit-font-smoothing:antialiased}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.center{margin-left:auto;margin-right:auto}
.spread{width:100%}
p.lead,.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{font-size:1.21875em;line-height:1.6}
.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:none}
p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol,ul.no-bullet,ol.no-bullet{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}
ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
ul.square{list-style-type:square}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.no-bullet{list-style:none}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}
abbr{text-transform:none}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}
blockquote cite:before{content:"\2014 \0020"}
blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media only screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}
table thead,table tfoot{background:#f7f8f7;font-weight:bold}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}
body{tab-size:4}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.clearfix:before,.clearfix:after,.float-group:before,.float-group:after{content:" ";display:table}
.clearfix:after,.float-group:after{clear:both}
*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menu{color:rgba(0,0,0,.8)}
b.button:before,b.button:after{position:relative;top:-1px;font-weight:400}
b.button:before{content:"[";padding:0 3px 0 2px}
b.button:after{content:"]";padding:0 2px 0 3px}
p a>code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header:before,#header:after,#content:before,#content:after,#footnotes:before,#footnotes:after,#footer:before,#footer:after{content:" ";display:table}
#header:after,#content:after,#footnotes:after,#footer:after{clear:both}
#content{margin-top:1.25em}
#content:before{content:none}
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8}
#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px}
#header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span:before{content:"\00a0\2013\00a0"}
#header .details br+span.author:before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
#header .details br+span#revremark:before{content:"\00a0|\00a0"}
#header #revnumber{text-transform:capitalize}
#header #revnumber:after{content:"\00a0"}
#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #efefed;padding-bottom:.5em}
#toc>ul{margin-left:.125em}
#toc ul.sectlevel0>li>a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media only screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}}
@media only screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2>ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
#content #toc>:first-child{margin-top:0}
#content #toc>:last-child{margin-bottom:0}
#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:rgba(255,255,255,.8);line-height:1.44}
.sect1{padding-bottom:.625em}
@media only screen and (min-width:768px){.sect1{padding-bottom:1.25em}}
.sect1+.sect1{border-top:1px solid #efefed}
#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1>a.anchor:before,h2>a.anchor:before,h3>a.anchor:before,#toctitle>a.anchor:before,.sidebarblock>.content>.title>a.anchor:before,h4>a.anchor:before,h5>a.anchor:before,h6>a.anchor:before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
table.tableblock>caption.title{white-space:nowrap;overflow:visible;max-width:0}
.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{color:rgba(0,0,0,.85)}
table.tableblock #preamble>.sectionbody>.paragraph:first-of-type p{font-size:inherit}
.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock>table td.icon{text-align:center;width:80px}
.admonitionblock>table td.icon img{max-width:none}
.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)}
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}
.exampleblock>.content>:first-child{margin-top:0}
.exampleblock>.content>:last-child{margin-bottom:0}
.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
.sidebarblock>:first-child{margin-top:0}
.sidebarblock>:last-child{margin-bottom:0}
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}
.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}
.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em}
.literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal}
@media only screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}
@media only screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}
.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.listingblock>.content{position:relative}
.listingblock code[data-lang]:before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}
.listingblock:hover code[data-lang]:before{display:block}
.listingblock.terminal pre .command:before{content:attr(data-prompt);padding-right:.5em;color:#999}
.listingblock.terminal pre .command:not([data-prompt]):before{content:"$"}
table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}
table.pyhltable td.code{padding-left:.75em;padding-right:0}
pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8}
pre.pygments .lineno{display:inline-block;margin-right:.25em}
table.pyhltable .linenodiv{background:none!important;padding-right:0!important}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote:before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right}
.quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)}
.quoteblock .quoteblock blockquote{padding:0 0 0 .75em}
.quoteblock .quoteblock blockquote:before{display:none}
.verseblock{margin:0 1em 1.25em 1em}
.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract{margin:0 0 1.25em 0;display:block}
.quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{text-align:left;word-spacing:0}
.quoteblock.abstract blockquote:before,.quoteblock.abstract blockquote p:first-of-type:before{display:none}
table.tableblock{max-width:100%;border-collapse:separate}
table.tableblock td>.paragraph:last-child p>p:last-child,table.tableblock th>p:last-child,table.tableblock td>p:last-child{margin-bottom:0}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all th.tableblock,table.grid-all td.tableblock{border-width:0 1px 1px 0}
table.grid-all tfoot>tr>th.tableblock,table.grid-all tfoot>tr>td.tableblock{border-width:1px 1px 0 0}
table.grid-cols th.tableblock,table.grid-cols td.tableblock{border-width:0 1px 0 0}
table.grid-all *>tr>.tableblock:last-child,table.grid-cols *>tr>.tableblock:last-child{border-right-width:0}
table.grid-rows th.tableblock,table.grid-rows td.tableblock{border-width:0 0 1px 0}
table.grid-all tbody>tr:last-child>th.tableblock,table.grid-all tbody>tr:last-child>td.tableblock,table.grid-all thead:last-child>tr>th.tableblock,table.grid-rows tbody>tr:last-child>th.tableblock,table.grid-rows tbody>tr:last-child>td.tableblock,table.grid-rows thead:last-child>tr>th.tableblock{border-bottom-width:0}
table.grid-rows tfoot>tr>th.tableblock,table.grid-rows tfoot>tr>td.tableblock{border-width:1px 0 0 0}
table.frame-all{border-width:1px}
table.frame-sides{border-width:0 1px}
table.frame-topbot{border-width:1px 0}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock>code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
td>div.verse{white-space:pre}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.unstyled,ol.unnumbered,ul.checklist,ul.none{list-style-type:none}
ul.unstyled,ol.unnumbered,ul.checklist{margin-left:.625em}
ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1em;font-size:.85em}
ul.checklist li>p:first-child>input[type="checkbox"]:first-child{width:1em;position:relative;top:1px}
ul.inline{margin:0 auto .625em auto;margin-left:-1.375em;margin-right:0;padding:0;list-style:none;overflow:hidden}
ul.inline>li{list-style:none;float:left;margin-left:1.375em;display:block}
ul.inline>li>*{display:block}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist>table,.colist>table{border:0;background:none}
.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist>table tr>td:first-of-type{padding:0 .75em;line-height:1}
.colist>table tr>td:last-of-type{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}
.imageblock.left,.imageblock[style*="float: left"]{margin:.25em .625em 1.25em 0}
.imageblock.right,.imageblock[style*="float: right"]{margin:.25em 0 1.25em .625em}
.imageblock>.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em 0;border-width:1px 0 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;text-indent:-1.05em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}
.gist .file-data>table td.line-data{width:99%}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background-color:#00fafa}
.black{color:#000}
.black-background{background-color:#000}
.blue{color:#0000bf}
.blue-background{background-color:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background-color:#fa00fa}
.gray{color:#606060}
.gray-background{background-color:#7d7d7d}
.green{color:#006000}
.green-background{background-color:#007d00}
.lime{color:#00bf00}
.lime-background{background-color:#00fa00}
.maroon{color:#600000}
.maroon-background{background-color:#7d0000}
.navy{color:#000060}
.navy-background{background-color:#00007d}
.olive{color:#606000}
.olive-background{background-color:#7d7d00}
.purple{color:#600060}
.purple-background{background-color:#7d007d}
.red{color:#bf0000}
.red-background{background-color:#fa0000}
.silver{color:#909090}
.silver-background{background-color:#bcbcbc}
.teal{color:#006060}
.teal-background{background-color:#007d7d}
.white{color:#bfbfbf}
.white-background{background-color:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background-color:#fafa00}
span.icon>.fa{cursor:default}
.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note:before{content:"\f05a";color:#19407c}
.admonitionblock td.icon .icon-tip:before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning:before{content:"\f071";color:#bf6900}
.admonitionblock td.icon .icon-caution:before{content:"\f06d";color:#bf3400}
.admonitionblock td.icon .icon-important:before{content:"\f06a";color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]:after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,span.alt{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@media print{@page{margin:1.25cm .75cm}
*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
a[href^="http:"]:not(.bare):after,a[href^="https:"]:not(.bare):after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]:after{content:" (" attr(title) ")"}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
#toc,.sidebarblock,.exampleblock>.content{background:none!important}
#toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important}
.sect1{padding-bottom:0!important}
.sect1+.sect1{border:0!important}
#header>h1:first-child{margin-top:1.25rem}
body.book #header{text-align:center}
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em 0}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span:before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
.listingblock code[data-lang]:before{display:block}
#footer{background:none!important;padding:0 .9375em}
#footer-text{color:rgba(0,0,0,.6)!important;font-size:.9em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
</style>
<style>
.hidden {
	display: none;
}

.switch {
	border-width: 1px 1px 0 1px;
	border-style: solid;
	border-color: #7a2518;
	display: inline-block;
}

.switch--item {
	padding: 10px;
	background-color: #ffffff;
	color: #7a2518;
	display: inline-block;
	cursor: pointer;
}

.switch--item.selected {
	background-color: #7a2519;
	color: #ffffff;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/zepto/1.2.0/zepto.min.js"></script>
<script type="text/javascript">
function addBlockSwitches() {
	$('.primary').each(function() {
		primary = $(this);
		createSwitchItem(primary, createBlockSwitch(primary)).item.addClass("selected");
		primary.children('.title').remove();
	});
	$('.secondary').each(function(idx, node) {
		secondary = $(node);
		primary = findPrimary(secondary);
		switchItem = createSwitchItem(secondary, primary.children('.switch'));
		switchItem.content.addClass('hidden');
		findPrimary(secondary).append(switchItem.content);
		secondary.remove();
	});
}

function createBlockSwitch(primary) {
	blockSwitch = $('<div class="switch"></div>');
	primary.prepend(blockSwitch);
	return blockSwitch;
}

function findPrimary(secondary) {
	candidate = secondary.prev();
	while (!candidate.is('.primary')) {
		candidate = candidate.prev();
	}
	return candidate;
}

function createSwitchItem(block, blockSwitch) {
	blockName = block.children('.title').text();
	content = block.children('.content').first().append(block.next('.colist'));
	item = $('<div class="switch--item">' + blockName + '</div>');
	item.on('click', '', content, function(e) {
		$(this).addClass('selected');
		$(this).siblings().removeClass('selected');
		e.data.siblings('.content').addClass('hidden');
		e.data.removeClass('hidden');
	});
	blockSwitch.append(item);
	return {'item': item, 'content': content};
}

$(addBlockSwitches);
</script>
</head>

<body class="article toc2 toc-left">
<div id="header">
<h1>Contracts on the Producer Side 2.1.3.BUILD-SNAPSHOT</h1>
<div id="toc" class="toc2">
<div id="toctitle">Table of Contents</div>
<ul class="sectlevel1">
<li><a href="#_scenarios">Scenarios</a></li>
<li><a href="#_flow">Flow</a></li>
<li><a href="#_tutorial">Tutorial</a>
<ul class="sectlevel2">
<li><a href="#_consumer_flow_1">Consumer flow 1</a>
<ul class="sectlevel3">
<li><a href="#_ide_setup">IDE setup</a></li>
<li><a href="#_cloning_the_producer_s_code">Cloning the producer&#8217;s code</a></li>
<li><a href="#_adding_dependencies_in_the_producer_s_clone">Adding dependencies in the producer&#8217;s clone</a></li>
<li><a href="#_defining_first_code_foo_consumer_code_http_contract">Defining first <code>foo-consumer</code> HTTP contract</a></li>
<li><a href="#_defining_the_second_code_foo_consumer_code_http_contract">Defining the Second <code>foo-consumer</code> HTTP Contract</a></li>
<li><a href="#_defining_code_bar_consumer_code_http_contracts">Defining <code>bar-consumer</code> HTTP contracts</a></li>
<li><a href="#_setting_up_the_spring_cloud_contract_plugin_on_the_producer_side">Setting up the Spring Cloud Contract plugin on the producer side</a></li>
<li><a href="#_writing_missing_implementation_on_the_consumer_side">Writing missing implementation on the consumer side</a></li>
<li><a href="#_turning_on_stub_runner_in_consumer_tests">Turning on Stub Runner in Consumer Tests</a></li>
</ul>
</li>
<li><a href="#_producer_flow_1">Producer flow 1</a>
<ul class="sectlevel3">
<li><a href="#_ide_setup_2">IDE setup</a></li>
<li><a href="#_setting_up_the_spring_cloud_contract_plugin">Setting up the Spring Cloud Contract plugin</a></li>
<li><a href="#_generating_tests_from_contracts">Generating tests from contracts</a></li>
<li><a href="#_fixing_broken_http_tests">Fixing broken HTTP tests</a></li>
</ul>
</li>
<li><a href="#_consumer_flow_2">Consumer flow 2</a></li>
<li><a href="#_generating_documentation_from_contracts">Generating documentation from contracts</a></li>
</ul>
</li>
<li><a href="#_solutions">Solutions</a>
<ul class="sectlevel2">
<li><a href="#_written_consumer_tests">Written consumer tests</a></li>
<li><a href="#_adding_spring_cloud_contract_dependency">Adding Spring Cloud Contract Dependency</a></li>
<li><a href="#_proposal_of_simple_contracts_by_consumer">Proposal of simple contracts by consumer</a></li>
<li><a href="#_missing_consumer_controller_code">Missing consumer controller code</a></li>
<li><a href="#_stub_logs">Stub Logs</a></li>
<li><a href="#_beer_request">Beer Request</a></li>
<li><a href="#_missing_listener_code">Missing listener code</a></li>
<li><a href="#_missing_triggers">Missing triggers</a></li>
<li><a href="#_messaging_dsls">Messaging DSLs</a></li>
<li><a href="#_producercontroller_implementation">ProducerController implementation</a></li>
<li><a href="#_beerrestbase">BeerRestBase</a></li>
<li><a href="#_beermessagingbase">BeerMessagingBase</a></li>
<li><a href="#_messaging_implementation">Messaging implementation</a></li>
<li><a href="#_foo_consumer_contracts">Foo-consumer contracts</a></li>
<li><a href="#_bar_consumer_contracts">Bar-consumer contracts</a></li>
<li><a href="#_stubs_per_consumer_beercontroller">Stubs Per Consumer BeerController</a></li>
<li><a href="#_producercontroller_for_stubs_per_consumer_implementation">ProducerController for stubs per consumer implementation</a></li>
</ul>
</li>
<li><a href="#_back_to_the_main_page">Back to the Main Page</a></li>
</ul>
</div>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>In this tutorial, we keep the contracts together with the producer code. Each consumer
defines the contracts in a dedicated folder. For the same requests, the consumers expect
different responses.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_scenarios">Scenarios</h2>
<div class="sectionbody">
<div class="paragraph">
<p>We must write the following features:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../images/scenario_stubs_per_consumer_1.png" alt="scenario stubs per consumer 1">
</div>
<div class="title">Figure 1. Unofficially addresses the person by name for positive beer selling via HTTP</div>
</div>
<div class="paragraph">
<p>&#160;
&#160;</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../images/scenario_stubs_per_consumer_2.png" alt="scenario stubs per consumer 2">
</div>
<div class="title">Figure 2. Unofficially addresses the person by name for negative beer selling via HTTP</div>
</div>
<div class="paragraph">
<p>&#160;
&#160;</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../images/scenario_stubs_per_consumer_3.png" alt="scenario stubs per consumer 3">
</div>
<div class="title">Figure 3. Officially addresses the person by surname for positive beer selling via HTTP</div>
</div>
<div class="paragraph">
<p>&#160;
&#160;</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../images/scenario_stubs_per_consumer_4.png" alt="scenario stubs per consumer 4">
</div>
<div class="title">Figure 4. Officially addresses the person by surname for negative beer selling via HTTP</div>
</div>
<div class="paragraph">
<p>&#160;
&#160;</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_flow">Flow</h2>
<div class="sectionbody">
<div class="imageblock">
<div class="content">
<img src="../images/flow.png" alt="flow">
</div>
<div class="title">Figure 5. Consumer Driven Contract Flow</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_tutorial">Tutorial</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Consumer Driven Contracts are like TDD in terms of architecture. We start by writing a
test on the consumer side. This time, we simulate in our single code base as if we had
two separate consumers. Normally, both consumers would have their own code bases, but,
for the sake of demonstration, we try to keep things simple.</p>
</div>
<div class="sect2">
<h3 id="_consumer_flow_1">Consumer flow 1</h3>
<div class="imageblock">
<div class="content">
<img src="../images/consumer_flow_1.png" alt="consumer flow 1">
</div>
<div class="title">Figure 6. Interact with cloned producer code</div>
</div>
<div class="sect3">
<h4 id="_ide_setup">IDE setup</h4>
<div class="ulist">
<ul>
<li>
<p>In your IDE, open the <code>consumer_with_stubs_per_consumer</code> project (either via Maven or
Gradle)</p>
</li>
<li>
<p>We have the following objectives for HTTP:</p>
<div class="ulist">
<ul>
<li>
<p>As a consumer with name <code>foo-service</code>:</p>
<div class="ulist">
<ul>
<li>
<p>For a client with a certain <code>name</code> and <code>age</code>, we ask the producer to verify whether
the person is eligible to get the beer.</p>
</li>
<li>
<p>We expect to retrieve the <code>status</code> and the <code>name</code> of the client.</p>
</li>
<li>
<p>Depending on the <code>status</code>, we either accept or decline giving a beer.</p>
</li>
<li>
<p>Since we have a friendly service, we address the client by <code>MY DEAR FRIEND</code> and then
use the person&#8217;s <code>name</code>.</p>
</li>
<li>
<p>If the person (for example, with the name, <code>marcin</code>) can get the beer then we say
<code>THERE YOU GO MY DEAR FRIEND [marcin]</code>.</p>
</li>
<li>
<p>Otherwise, we say <code>GET LOST MY DEAR FRIEND [marcin]</code>.</p>
</li>
</ul>
</div>
</li>
<li>
<p>As a consumer with name <code>bar-service</code>:</p>
<div class="ulist">
<ul>
<li>
<p>For the client with a certain <code>name</code> and <code>age</code>, we ask the producer to verify whether
the person is eligible to get the beer.</p>
</li>
<li>
<p>We expect to retrieve the <code>status</code> and the <code>surname</code> of the client (for simplicity we
receive the provided <code>name</code> as <code>surname</code>).</p>
</li>
<li>
<p>Depending on the <code>status</code>, we either accept or decline giving a beer.</p>
</li>
<li>
<p>Since we have a very official service, we address the client by <code>MR</code>.</p>
</li>
<li>
<p>If the person (for example, with the name, <code>marcin</code>) can get the beer, then we say
<code>THERE YOU GO MR [marcin]</code>, Where <code>marcin</code> came back from the producer service as a
<code>surname</code>.</p>
</li>
<li>
<p>Otherwise, we say <code>GET LOST MR [marcin]</code>.</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
<li>
<p>Normally we would do TDD, but we already have some code ready to speed things up.</p>
</li>
<li>
<p>In the <code>BeerController</code> class, you can see that the implementation of the method is
missing. We return to that later. For now, you can see that we have a <code>/beer</code> endpoint
that expects a JSON request body that maps to a <code>Person</code> class.</p>
</li>
<li>
<p>Now open the <code>BeerControllerTest</code> and write the missing test bodies.</p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">	@Test public void should_give_me_a_beer_when_im_old_enough() throws Exception {
		//remove::start[]
		this.mockMvc.perform(MockMvcRequestBuilders.post("/beer")
				.contentType(MediaType.APPLICATION_JSON)
				.content(this.json.write(new Person("marcin", 22)).getJson()))
				.andExpect(status().isOk())
				.andExpect(content().string("THERE YOU GO MY DEAR FRIEND [marcin]"));
		//remove::end[]
	}

	@Test public void should_reject_a_beer_when_im_too_young() throws Exception {
		//remove::start[]
		this.mockMvc.perform(MockMvcRequestBuilders.post("/beer")
				.contentType(MediaType.APPLICATION_JSON)
				.content(this.json.write(new Person("marcin", 17)).getJson()))
				.andExpect(status().isOk())
				.andExpect(content().string("GET LOST MY DEAR FRIEND [marcin]"));
		//remove::end[]
	}</code></pre>
</div>
</div>
<div class="paragraph">
<p>We need to name our consumer somehow. The best way is to provide that value in the
<code>properties</code> attribute in a <code>SpringBootTest</code> annotation, though you also could pass it
via a file, such as <code>application.yml</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@SpringBootTest(webEnvironment = WebEnvironment.MOCK,
		properties = {"spring.application.name=foo-consumer"})</code></pre>
</div>
</div>
<div class="paragraph">
<p>If we run the tests, they fail, because we have no implementation.
Now open <code>BeerControllerForBarTest</code>. In this test class, we simulate that we are using
the <code>bar-service</code> and not the <code>foo-service</code>. We can start with the missing test
implementation.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">	@Test public void should_give_me_a_beer_when_im_old_enough() throws Exception {
		//remove::start[]
		this.mockMvc.perform(MockMvcRequestBuilders.post("/beer")
				.contentType(MediaType.APPLICATION_JSON)
				.content(this.json.write(new Person("marcin", 22)).getJson()))
				.andExpect(status().isOk())
				.andExpect(content().string("THERE YOU GO MR [marcin]"));
		//remove::end[]
	}

	@Test public void should_reject_a_beer_when_im_too_young() throws Exception {
		//remove::start[]
		this.mockMvc.perform(MockMvcRequestBuilders.post("/beer")
				.contentType(MediaType.APPLICATION_JSON)
				.content(this.json.write(new Person("marcin", 17)).getJson()))
				.andExpect(status().isOk())
				.andExpect(content().string("GET LOST MR [marcin]"));
		//remove::end[]
	}</code></pre>
</div>
</div>
<div class="paragraph">
<p>In this test, we do not set the <code>spring.application.name</code>. We will change the name with
an attribute in an annotation later.
Now we want to write an implementation, but the problem is that we do not yet know what
API we would like to have. Here, we touch the very essence of Consumer Driven
Contracts. As consumers, we want to drive the change of the API. That is why, <strong>as
consumers</strong>, we work on the producer code.</p>
</div>
</div>
<div class="sect3">
<h4 id="_cloning_the_producer_s_code">Cloning the producer&#8217;s code</h4>
<div class="ulist">
<ul>
<li>
<p>In this tutorial we will not clone the producer&#8217;s code, we&#8217;ll just open it in the IDE</p>
</li>
<li>
<p>There&#8217;s some production code written on the producer side but you could completely remove it. The idea
of CDC is that defining of contract can be done without writing a single line of code for the feature.</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_adding_dependencies_in_the_producer_s_clone">Adding dependencies in the producer&#8217;s clone</h4>
<div class="ulist">
<ul>
<li>
<p>Since we want the IDE to help us with code completion, let&#8217;s add the necessary Spring Cloud Contract
dependencies. You need to add <code>spring-cloud-starter-contract-verifier</code> as a test dependency</p>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-xml" data-lang="xml">&lt;dependency&gt;
	&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
	&lt;artifactId&gt;spring-cloud-starter-contract-verifier&lt;/artifactId&gt;
	&lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">testCompile("org.springframework.cloud:spring-cloud-starter-contract-verifier")</code></pre>
</div>
</div>
</li>
<li>
<p>This is a task that you would do once only since when you&#8217;ll be adding next contracts
all the dependencies will already be added</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_defining_first_code_foo_consumer_code_http_contract">Defining first <code>foo-consumer</code> HTTP contract</h4>
<div class="paragraph">
<p>It is time to play with the API Create a <code>src/test/resources/contracts/foo-consumer/rest</code>
folder. You can define the contracts using Groovy DSL. To create your first HTTP
contract:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Under the <code>rest</code> folder, create a file called <code>shouldGrantABeerIfOldEnough.groovy</code></p>
</li>
<li>
<p>Call the <code>Contract.make</code> method to start defining the contract.</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {

}</code></pre>
</div>
</div>
<div class="paragraph">
<p>You can call <code>description()</code> method to provide some meaningful description.</p>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<div class="title">Tip</div>
</td>
<td class="content">
You can use the Groovy multiline String <code>""" """</code> to have all special characters
escaped. Every new line in the String is converted into a new line character, as shown in
the following example:
</td>
</tr>
</table>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">Contract.make {
	request {
		description("""
Represents a successful scenario of getting a beer

```
given:
	client is old enough
when:
	he applies for a beer
then:
	we'll grant him the beer
```
""")
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now call the <code>request { }</code> and <code>response { }</code> methods, as shown in the following example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        some interesting description
    """)
    request {
    }
    response {
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Let&#8217;s assume that we want to send a <code>POST</code> method. To do so, call <code>method POST()</code> or
<code>method "POST"</code>.</p>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<div class="title">Tip</div>
</td>
<td class="content">
In Groovy, you do not need to provide parentheses (in most cases). You can write
either <code>method POST()</code> or <code>method(POST())</code>. The result is the same.
</td>
</tr>
</table>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        some interesting description
    """)
    request {
        method POST()
    }
    response {
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now we need to provide a URL: <code>/check</code>. We can write <code>url "/check"</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        some interesting description
    """)
    request {
        method POST()
        url "/check"
    }
    response {
    }
}</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>Now we need to define the body. We leverage some of Groovy&#8217;s power here, so, if you
get lost you can always check the <a href="http://groovy-lang.org/json.html">Groovy JSON
documentation</a>. Let&#8217;s call the <code>body()</code> method with brackets.</p>
</li>
<li>
<p>In Groovy, you can use the map notation this way: <code>[key: "value", secondKey: 2]</code>. In
the same way, we can describe the body with JSON. We want to send JSON such as the
following <code>{ "age": 22, "name": "marcin" }</code>. To do so, we can create a map notation of
<code>[age:22, name:"marcin"]</code>. The <code>body</code> method accepts a map. In Groovy, if a method
accepts a map, then the <code>[]</code> brackets can be omitted. So you can write either
<code>body([age:22, name:"marcin"])</code> or <code>body(age:22, name:"marcin")</code>.</p>
</li>
<li>
<p>Let&#8217;s assume that we already want to be more generic about our contract and we want to
verify that the age is greater than 20 and that name is any alphaunicode character. We
can use the <code>$()</code> or <code>value()</code> methods that Spring Cloud Contract provides to define
dynamic behaviour.</p>
</li>
<li>
<p>We use the <code>$(regex(&#8230;&#8203;))</code> method to define the age and the <code>$(anyAlphaUnicode())</code> for
the name.</p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
Represents a successful scenario of getting a beer

```
given:
	client is old enough
when:
	he applies for a beer
then:
	we'll grant him the beer
```
    """)
    request {
        method POST()
        url "/check"
        body(
                age: $(regex("[2-9][0-9]")),
                name: $(anyAlphaUnicode())
            )
    }
    response {
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now we can work on the headers, by calling the <code>headers { }</code> method, as shown in the
following example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
Represents a successful scenario of getting a beer

```
given:
	client is old enough
when:
	he applies for a beer
then:
	we'll grant him the beer
```
    """)
    request {
        method POST()
        url "/check"
        body(
                age: $(regex("[2-9][0-9]")),
                name: $(anyAlphaUnicode())
            )
        headers {

        }
    }
    response {
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Inside that method, we want to use the <code>Content-Type: "application/json</code> header. To do
so, call <code>contentType(applicationJson())</code> methods, as shown in the following example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
Represents a successful scenario of getting a beer

```
given:
	client is old enough
when:
	he applies for a beer
then:
	we'll grant him the beer
```
    """)
    request {
        method POST()
        url "/check"
        body(
                age: $(regex("[2-9][0-9]")),
                name: $(anyAlphaUnicode())
            )
        headers {
            contentType(applicationJson())
        }
    }
    response {
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Congratulations! You defined the contract for the request. Now we can work on the
response</p>
</div>
<div class="paragraph">
<p>In the <code>response</code> block, we want to define that the status of our response will be 200.
To do so, call <code>status 200</code>, as shown in the following example:</p>
</div>
<div class="paragraph">
<p>+</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
Represents a successful scenario of getting a beer

```
given:
	client is old enough
when:
	he applies for a beer
then:
	we'll grant him the beer
```
    """)
    request {
        method POST()
        url "/check"
        body(
                age: $(regex("[2-9][0-9]")),
                name: $(anyAlphaUnicode())
            )
        headers {
            contentType(applicationJson())
        }
    }
    response {
        status 200
    }
}</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>We want our response to have a body. As you might have guessed, there&#8217;s a <code>body</code> method
here, too. We can now use another way of defining bodies by using String. (That is the
less preferred option in Spring Cloud Contract, but it can still be useful.)</p>
</li>
<li>
<p>We want to send back a field called <code>status</code> that will return <code>OK</code> when the person can
get the beer. The <code>foo-consumer</code> is also interested in getting the name in the response
from the request.</p>
<div class="ulist">
<ul>
<li>
<p>To reference the request from the response via the JSON path, you can call the
<code>fromRequest()</code> method. In the following code snippet, we reference the <code>name</code> field from
the request: `fromRequest().body('$.name')".</p>
</li>
<li>
<p>In Groovy, when you use a multiline string (<code>""" """</code>), you can call the <code>${}</code>
interpolation mechanism to call a method from within a String.</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<div class="title">Tip</div>
</td>
<td class="content">
Don&#8217;t confuse the <code>$()</code> from Spring Cloud Contract with the <code>${}</code> interpolation
mechanism. Call
<code>body(""" { "status" : "OK", "name": "${fromRequest().body('$.name')}" } """)</code>. That way,
you can define how the response body looks by providing the exact JSON value, and inside
that JSON you can also provide dynamic values. In our case, for the <code>name</code> response
field, we provide the value of <code>name</code> from the request, as shown in the following
example:
</td>
</tr>
</table>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
Represents a successful scenario of getting a beer

```
given:
	client is old enough
when:
	he applies for a beer
then:
	we'll grant him the beer
```
    """)
    request {
        method POST()
        url "/check"
        body(
                age: $(regex("[2-9][0-9]")),
                name: $(anyAlphaUnicode())
            )
        headers {
            contentType(applicationJson())
        }
    }
    response {
        status 200
        body("""
            {
                "status" : "OK",
                "name": "${fromRequest().body('$.name')}"
            }
        """)
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The last thing to add is the response headers. We do just about exactly the same thing as
we did previously for the request, as shown here:
<code>headers { contentType(applicationJson()) }</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
Represents a successful scenario of getting a beer

```
given:
	client is old enough
when:
	he applies for a beer
then:
	we'll grant him the beer
```
    """)
    request {
        method POST()
        url "/check"
        body(
                age: $(regex("[2-9][0-9]")),
                name: $(anyAlphaUnicode())
            )
        headers {
            contentType(applicationJson())
        }
    }
    response {
        status 200
        body("""
            {
                "status" : "OK",
                "name": "${fromRequest().body('$.name')}"
            }
        """)
        headers {
            contentType(applicationJson())
        }
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Congratulations! You have created your first contract!</p>
</div>
</div>
<div class="sect3">
<h4 id="_defining_the_second_code_foo_consumer_code_http_contract">Defining the Second <code>foo-consumer</code> HTTP Contract</h4>
<div class="paragraph">
<p>Now it&#8217;s time for you to create the second contract. Create a file called
 <code>shouldRejectABeerIfTooYoung.groovy</code>.
If you get lost, look at the <a href="#_foo_consumer_contracts">solution</a>.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Set the <code>age</code> in the request to the following regular expression <code>[0-1][0-9]</code>.</p>
</li>
<li>
<p>Update the response body to return a <code>status</code> of <code>NOT_OK</code>.</p>
</li>
<li>
<p>Update the description.</p>
</li>
</ol>
</div>
</div>
<div class="sect3">
<h4 id="_defining_code_bar_consumer_code_http_contracts">Defining <code>bar-consumer</code> HTTP contracts</h4>
<div class="paragraph">
<p>Let&#8217;s now move to the <code>bar-consumer</code>. Create a
<code>src/test/resources/contracts/bar-consumer/rest</code> folder. We will create very similar
contracts to the <code>foo-consumer</code> one. The only difference is that the response contains a
<code>surname</code> field instead of a <code>name</code> field. Create 2 files named
<code>shouldGrantABeerIfOldEnough.groovy</code> and <code>shouldRejectABeerIfTooYoung.groovy</code> and fill
them out <a href="#_bar_consumer_contracts">or copy from the solution</a>. We have written the
contracts. It is time to publish some stubs!</p>
</div>
</div>
<div class="sect3">
<h4 id="_setting_up_the_spring_cloud_contract_plugin_on_the_producer_side">Setting up the Spring Cloud Contract plugin on the producer side</h4>
<div class="ulist">
<ul>
<li>
<p>Ok, at this moment we&#8217;ve described the API that would be interesting for us, consumers, and most likely
will suit our needs. We define those contracts cause we want to have some stubs produced for us without
needing to write a single line of the implementation code. The tool that we need to do this conversion
is the Spring Cloud Contract plugin. Let&#8217;s add it to the producer&#8217;s <code>pom.xml</code> / <code>build.gradle</code>.</p>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-xml" data-lang="xml">&lt;plugin&gt;
    &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
    &lt;artifactId&gt;spring-cloud-contract-maven-plugin&lt;/artifactId&gt;
    &lt;version&gt;${spring-cloud-contract.version}&lt;/version&gt;
    &lt;extensions&gt;true&lt;/extensions&gt;
&lt;/plugin&gt;</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">buildscript {
	dependencies {
		classpath "org.springframework.cloud:spring-cloud-contract-gradle-plugin:${verifierVersion}"
	}
}</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>The coordinates of the plugin are: <code>org.springframework.cloud:spring-cloud-contract-gradle-plugin:$2.1.3.BUILD-SNAPSHOT</code></p>
</li>
<li>
<p>For this tutorial we&#8217;re using latest snapshot versions that you can reference via the Maven&#8217;s
<code>${spring-cloud-contract.version}</code> property or Gradle&#8217;s <code>verifierVersion</code> one</p>
</li>
<li>
<p>Once the plugin has been added just call the commands to install the stubs locally</p>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">$ ./mvnw clean install -DskipTests</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">$ ./gradlew clean build publishToMavenLocal -x test</code></pre>
</div>
</div>
</li>
<li>
<p>Now you can check out <code>target/stubs/META-INF/com.example/beer-api-producer-with-stubs-per-consumer/0.0.1-SNAPSHOT</code> for Maven or
<code>build/stubs/META-INF/com.example/beer-api-producer-with-stubs-per-consumer/0.0.1-SNAPSHOT</code> for Gradle. Over there you&#8217;ll see
<code>contracts</code> folder where all contracts got copied and the <code>mappings</code> folder where you&#8217;ll find all the
generated stubs. By default Spring Cloud Contract uses <a href="http://wiremock.org">WireMock</a> as an implementation
of fake HTTP server. Under the <code>rest</code> subfolder you&#8217;ll see all the generated stubs. Notice that
we&#8217;re using JSON Paths to check the contents of the request.</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_writing_missing_implementation_on_the_consumer_side">Writing missing implementation on the consumer side</h4>
<div class="paragraph">
<p>We know what the API should look like. Let&#8217;s go to <code>BeerController</code> and write the
missing implementation <a href="#_stubs_per_consumer_beercontroller">or copy from the solution</a>.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>We want to send a POST HTTP method to <code><a href="http://localhost:8090/check" class="bare">http://localhost:8090/check</a></code>.</p>
</li>
<li>
<p>The JSON body will contain the <code>Person</code> that we received in the controller.</p>
</li>
<li>
<p>Depending on the status (<code>OK</code> or <code>NOT_OK</code>), we send back:</p>
<div class="ulist">
<ul>
<li>
<p>For <code>OK</code>: <code>THERE YOU GO ` + the result of the `message(body of the response)</code> method.</p>
</li>
<li>
<p>For <code>NOT_OK</code>: <code>GET LOST ` + the result of the `message(body of the response)</code> method.</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
<div class="paragraph">
<p>If we run the <code>BeerControllerTest</code> and <code>BeerControllerForBarTest</code>, they both fail due
to the connection being refused. Let&#8217;s fix that.</p>
</div>
</div>
<div class="sect3">
<h4 id="_turning_on_stub_runner_in_consumer_tests">Turning on Stub Runner in Consumer Tests</h4>
<div class="paragraph">
<p>Since we managed to install the stubs locally and we now have the missing implementation
written, we can now go back to the consumer tests. Let&#8217;s add the Spring Cloud Contract
Stub Runner as a dependency, as shown in the following example:</p>
</div>
<div class="paragraph">
<p>+</p>
</div>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-xml" data-lang="xml">&lt;dependency&gt;
	&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
	&lt;artifactId&gt;spring-cloud-starter-contract-stub-runner&lt;/artifactId&gt;
	&lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>+</p>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">testCompile("org.springframework.cloud:spring-cloud-starter-contract-stub-runner")</code></pre>
</div>
</div>
<div class="paragraph">
<p>Let&#8217;s check out the <code>BeerControllerTest</code> and add the Stub Runner functionality, as shown
in the following example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@AutoConfigureStubRunner(stubsMode = StubRunnerProperties.StubsMode.LOCAL,
		ids = "com.example:beer-api-producer-with-stubs-per-consumer",
		stubsPerConsumer = true)</code></pre>
</div>
</div>
<div class="paragraph">
<p>You can see that we turned on the <code>stubsPerConsumer</code> flag. Doing so means that the path
of stubs is scanned and only those that contain the value of <code>spring.application.name</code>
is picked. Now let&#8217;s run the test. It should pass. Let&#8217;s try to fix the
<code>BeerControllerForBarTest</code>. We do not want to set the <code>spring.application.name</code>. That&#8217;s
why we will set that name on the <code>@AutoConfigureStubRunner</code> annotation via the
<code>consumerName</code> property. (Note that we also have to turn on the <code>stubsPerConsumer</code> flag.)</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@AutoConfigureStubRunner(stubsMode = StubRunnerProperties.StubsMode.LOCAL,
		ids = "com.example:beer-api-producer-with-stubs-per-consumer",
		stubsPerConsumer = true,
		consumerName = "bar-consumer")</code></pre>
</div>
</div>
<div class="paragraph">
<p>Congratulations! As a consumer, you successfully used the API of the producer for both
HTTP and messaging. Now we can file a pull request (PR) to their code to propose a
contract. Let&#8217;s switch to the producer side.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_producer_flow_1">Producer flow 1</h3>
<div class="imageblock">
<div class="content">
<img src="../images/producer_flow_1.png" alt="producer flow 1">
</div>
<div class="title">Figure 7. Producer takes over the PR, writes missing impl and merges the PR</div>
</div>
<div class="sect3">
<h4 id="_ide_setup_2">IDE setup</h4>
<div class="ulist">
<ul>
<li>
<p>Open in your IDE the <code>producer</code> project (either via Maven or Gradle)</p>
</li>
<li>
<p>We&#8217;re assuming that we&#8217;ve taken over the PR. Example of how to achieve that in "real life" for a PR
that got submitted to via a branch called <code>the_pr</code> looks like this:</p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">git fetch origin
git checkout -b the_pr origin/the_pr
git merge master</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>The idea of Spring Cloud Contract is about stub and contract validity. Right now we have a set of
contracts defined but we haven&#8217;t tested it against the producer side. Time to change that!</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_setting_up_the_spring_cloud_contract_plugin">Setting up the Spring Cloud Contract plugin</h4>
<div class="ulist">
<ul>
<li>
<p>Spring Cloud Contract can generate tests from your contracts to ensure that your implementation&#8217;s API
is compatible with the defined contract. Let&#8217;s set up the project to start generating tests.</p>
<div class="ulist">
<ul>
<li>
<p>Spring Cloud Contract needs a base class that all of the generated tests will extend. Currently
we support 3 different ways of defining a base class (you can read more about this in the
Spring Cloud Contract documentation for <a href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#_configure_plugin">Gradle</a>
and <a href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#_configure_plugin_2">Maven</a>)</p>
<div class="ulist">
<ul>
<li>
<p>a single class for all tests</p>
</li>
<li>
<p>convention based naming (takes 2 last package names and appends <code>Base</code>. Having a contract
<code>src/test/resources/contracts/foo/bar/shouldDoSth.groovy</code> would create a test class called
<code>BarTest</code> that would extend <code>FooBarBase</code> class.</p>
</li>
<li>
<p>manual mapping (you can state that contracts matching certain regular expression will have to
have a base class with fully qualified name equal to X)</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
</ul>
</div>
<div class="paragraph">
<p>In our situation, we use the mapping approach. Let&#8217;s set the following base classes for
our contracts, as shown in the following example:</p>
</div>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-xml" data-lang="xml">&lt;plugin&gt;
    &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
    &lt;artifactId&gt;spring-cloud-contract-maven-plugin&lt;/artifactId&gt;
    &lt;version&gt;${spring-cloud-contract.version}&lt;/version&gt;
    &lt;extensions&gt;true&lt;/extensions&gt;
    &lt;configuration&gt;
        &lt;baseClassMappings&gt;
            &lt;baseClassMapping&gt;
                &lt;contractPackageRegex&gt;.*rest.*&lt;/contractPackageRegex&gt;
                &lt;baseClassFQN&gt;com.example.BeerRestBase&lt;/baseClassFQN&gt;
            &lt;/baseClassMapping&gt;
        &lt;/baseClassMappings&gt;
    &lt;/configuration&gt;
&lt;/plugin&gt;</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">contracts {
	baseClassMappings {
		baseClassMapping(".*rest.*", "com.example.BeerRestBase")
	}
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="_generating_tests_from_contracts">Generating tests from contracts</h4>
<div class="ulist">
<ul>
<li>
<p>Let&#8217;s generate the tests! Just call:</p>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">$ ./mvnw clean install</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">$ ./gradlew clean build publishToMavenLocal</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>Suddenly some tests should start failing. Those tests are the autogenerated tests created
by Spring Cloud Contract</p>
</li>
<li>
<p>The tests lay under <code>/generated-test-sources/contracts/org/springframework/cloud/contract/verifier/tests/beer</code>
in <code>target</code> for Maven or <code>build</code> for Gradle</p>
</li>
<li>
<p>There will be a test for each folder in which you store your contracts. The name of the test class
will be the name of that folder</p>
</li>
<li>
<p>Each of the contracts will be a single test inside that test class</p>
</li>
<li>
<p>If you check out the generated tests you&#8217;ll notice that the dynamic parts of the <code>request</code> part
of the contract got converted to a concrete value. Any dynamic bits on the <code>response</code> side would be
converted into matchers.</p>
</li>
</ul>
</div>
</li>
<li>
<p>Time to fix the broken tests. We need to do that by providing the missing implementation.</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_fixing_broken_http_tests">Fixing broken HTTP tests</h4>
<div class="paragraph">
<p>Let&#8217;s start with HTTP. First, let&#8217;s write the missing implementation in
<code>ProducerController</code>. The logic to be written is as follows: If the
<code>personCheckingService.shouldGetBeer(&#8230;&#8203;)</code> returns <code>true</code>, then we should return
<code>new Response(BeerCheckStatus.OK, personToCheck.name)</code>. Otherwise, we should return
<code>new Response(BeerCheckStatus.NOT_OK, personToCheck.name)</code>.
(<a href="#_producerController_for_stubs_per_consumer_implementation">Show solution</a>).</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Let&#8217;s fix the <code>BeerRestBase</code> class now</p>
<div class="ulist">
<ul>
<li>
<p>The idea of CDC is <strong>NOT TO TEST</strong> every single feature. Contract tests are there to see if the API
is matched, <strong>NOT</strong> that the feature is working. That&#8217;s why we shouldn&#8217;t be accessing databases etc.
That means that we will work with mock of the <code>PersonCheckingService</code>. (<a href="#_beerrestbase">Show solution</a>)</p>
</li>
<li>
<p>Let&#8217;s annotate the test class with <code>@RunWith(MockitoJUnitRunner.class)</code> to enable Mockito runner.</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@RunWith(MockitoJUnitRunner.class)
public abstract class BeerRestBase {
...
}</code></pre>
</div>
</div>
</li>
<li>
<p>We&#8217;ll want to test the <code>ProducerController</code> so we can create a field <code>@InjectMocks ProducerController
producerController</code>. Mockito will inject any mocks for us via the constructor.</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">    @Mock PersonCheckingService personCheckingService;
    @InjectMocks ProducerController producerController;

    @Before
    public void setup() {
        given(personCheckingService.shouldGetBeer(argThat(oldEnough()))).willReturn(true);
    }</code></pre>
</div>
</div>
</li>
<li>
<p>It won&#8217;t compile cause we don&#8217;t have the <code>oldEnough()</code> method but don&#8217;t worry. So this line stubs
the <code>shouldGetBeer</code> method in such a way that if the user is old enough then the method will return
true. Let&#8217;s now add the <code>oldEnoughMethod()</code></p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">	private TypeSafeMatcher&lt;PersonToCheck&gt; oldEnough() {
		return new TypeSafeMatcher&lt;PersonToCheck&gt;() {
			@Override protected boolean matchesSafely(PersonToCheck personToCheck) {
				return personToCheck.age &gt;= 20;
			}
			@Override public void describeTo(Description description) {
			}
		};
	}</code></pre>
</div>
</div>
</li>
<li>
<p>We&#8217;re using the <code>TypeSafeMatcher</code> from Hamcrest to create a matcher for <code>PersonToCheck</code>. In this case
if the person to check is older or is 20 then the method <code>shouldGetBeer</code> method will return <code>true</code>.</p>
</li>
<li>
<p>Now we need to configure <a href="http://rest-assured.io/">RestAssured</a> that is used by Spring Cloud Contract
to send requests. In our case we want to profit from MockMvc. In order to set the <code>ProducerController</code>
with RestAssured it&#8217;s enough to call <code>RestAssuredMockMvc.standaloneSetup(producerController);</code></p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@RunWith(MockitoJUnitRunner.class)
public abstract class BeerRestBase {

    @Mock PersonCheckingService personCheckingService;
    @InjectMocks ProducerController producerController;

    @Before
    public void setup() {
        given(personCheckingService.shouldGetBeer(argThat(oldEnough()))).willReturn(true);
        RestAssuredMockMvc.standaloneSetup(producerController);
    }

    private TypeSafeMatcher&lt;PersonToCheck&gt; oldEnough() {
        return new TypeSafeMatcher&lt;PersonToCheck&gt;() {
            @Override protected boolean matchesSafely(PersonToCheck personToCheck) {
                return personToCheck.age &gt;= 20;
            }
            @Override public void describeTo(Description description) {
            }
        };
    }
}</code></pre>
</div>
</div>
</li>
<li>
<p>With mocks and RestAssured setup - we&#8217;re ready to run our HTTP based autogenerated tests</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
<div class="paragraph">
<p>Now you can merge the pull request to <code>master</code> and your CI system can build a fat jar and
the stubs.</p>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<div class="title">Important</div>
</td>
<td class="content">
Per consumer stubs is a powerful feature. On the producer side, if you want to
remove a field from the response, you can quickly verify if gets used. Try removing
the <code>surname</code> field from the <code>Response</code> class. You can see that the generated <code>RestTest</code>
in the <code>bar-consumer</code> subfolder fails. That means that the <code>bar-consumer</code> requires the
<code>surname</code> field and that you can&#8217;t safely remove it. On the other hand, in production,
both consumers receive more fields than they define in the contract. Thus, if they do not
configure their serializers properly (to ignore unknown fields), then their tests pass
but their integrations fail.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Congratulations! You have completed the producer side of this tutorial.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_consumer_flow_2">Consumer flow 2</h3>
<div class="imageblock">
<div class="content">
<img src="../images/consumer_flow_2.png" alt="consumer flow 2">
</div>
<div class="title">Figure 8. Switch to work online</div>
</div>
<div class="ulist">
<ul>
<li>
<p>After merging the PR the producer&#8217;s stubs reside in some Artifactory / Nexus instance</p>
</li>
<li>
<p>As consumers we no longer want to retrieve the stubs from our local Maven repository -
we&#8217;d like to download them from the remote location</p>
</li>
<li>
<p>To do that (we won&#8217;t do that for the tutorial but you would do it in your "production"
code) it&#8217;s enough to pass the <code>repositoryRoot</code> parameter and set the
<code>stubsMode</code> to <code>StubRunnerProperties.StubsMode.REMOTE</code></p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.MOCK)
@AutoConfigureMockMvc
@AutoConfigureJsonTesters
@AutoConfigureStubRunner(
repositoryRoot="http://www.foo.com/bar,
ids = "com.example:beer-api-producer-with-stubs-per-consumer:+:stubs:8090",
stubsMode = StubRunnerProperties.StubsMode.REMOTE
)
@DirtiesContext
public class YourTestOnTheConsumerSide extends AbstractTest {
}</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>Another option is to pass the property <code>stubrunner.repositoryRoot</code> either as a
system / environment property, or via an <code>application.yml</code> and <code>stubrunner.stubs-mode</code>
equal to <code>remote</code></p>
</li>
</ul>
</div>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_generating_documentation_from_contracts">Generating documentation from contracts</h3>
<div class="paragraph">
<p>Another feature of Spring Cloud Contract is an option to easily create the documentation
of the whole API of the producer. You can create the following test that will generate a
<code>contracts.adoc</code> file under <code>target/generated-snippets/</code> with description of contracts and
with the contract bodies as such.</p>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<div class="title">Tip</div>
</td>
<td class="content">
This test is a poor man&#8217;s version of the documentation generation. You can customize
it as you wish - the current version is just to show you an example.
</td>
</tr>
</table>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">package docs;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.contract.spec.Contract;
import org.springframework.cloud.contract.verifier.util.ContractVerifierDslConverter;
import org.springframework.core.io.Resource;
import org.springframework.test.context.junit4.SpringRunner;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Collection;
import java.util.regex.Pattern;

@RunWith(SpringRunner.class)
public class GenerateAdocsFromContractsTests {

	// TODO: Can be parametrized
	@Value("classpath:contracts") Resource contracts;
	private static String header = "= Application Contracts\n" + "\n"
			+ "In the following document you'll be able to see all the contracts that are present for this application.\n"
			+ "\n" + "== Contracts\n";

	@Test public void should_convert_contracts_into_adoc() throws IOException {
		final StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.append(header);
		final Path rootDir = this.contracts.getFile().toPath();

		Files.walkFileTree(rootDir, new FileVisitor&lt;Path&gt;() {
			private Pattern pattern = Pattern.compile("^.*groovy$");

			@Override
			public FileVisitResult preVisitDirectory(Path path, BasicFileAttributes atts)
					throws IOException {
				return FileVisitResult.CONTINUE;
			}

			@Override
			public FileVisitResult visitFile(Path path, BasicFileAttributes mainAtts)
					throws IOException {
				boolean matches = this.pattern.matcher(path.toString()).matches();
				if (matches) {
					appendContract(stringBuilder, path);
				}
				return FileVisitResult.CONTINUE;
			}

			@Override
			public FileVisitResult postVisitDirectory(Path path, IOException exc)
					throws IOException {
				return FileVisitResult.CONTINUE;
			}

			@Override public FileVisitResult visitFileFailed(Path path, IOException exc)
					throws IOException {
				// If the root directory has failed it makes no sense to continue
				return path.equals(rootDir) ?
						FileVisitResult.TERMINATE :
						FileVisitResult.CONTINUE;
			}
		});

		//String outputAdoc = asciidoctor.convert(stringBuilder.toString(), new HashMap&lt;String, Object&gt;());
		String outputAdoc = stringBuilder.toString();
		// TODO: Can be parametrized
		File outputDir = new File("target/generated-snippets");
		outputDir.mkdirs();
		// TODO: Can be parametrized
		File outputFile = new File(outputDir, "contracts.adoc");
		if (outputFile.exists()) {
			outputFile.delete();
		}
		if (outputFile.createNewFile()) {
			Files.write(outputFile.toPath(), outputAdoc.getBytes());
		}
	}

	static StringBuilder appendContract(final StringBuilder stringBuilder, Path path)
			throws IOException {
		Collection&lt;Contract&gt; contracts = ContractVerifierDslConverter.convertAsCollection(path.getParent().toFile(), path.toFile());
		// TODO: Can be parametrized
		contracts.forEach(contract -&gt; {
			stringBuilder.append("### ")
					.append(path.getFileName().toString())
					.append("\n\n")
					.append(contract.getDescription())
					.append("\n\n")
					.append("#### Contract structure")
					.append("\n\n")
					.append("[source,java,indent=0]")
					.append("\n")
					.append("----")
					.append("\n")
					.append(fileAsString(path))
					.append("\n")
					.append("----")
					.append("\n\n");
		});
		return stringBuilder;
	}

	static String fileAsString(Path path) {
		try {
			byte[] encoded = Files.readAllBytes(path);
			return new String(encoded, StandardCharsets.UTF_8);
		}
		catch (IOException e) {
			throw new RuntimeException(e);
		}
	}
}</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_solutions">Solutions</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_written_consumer_tests">Written consumer tests</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">	@Test
	public void should_give_me_a_beer_when_im_old_enough() throws Exception {
		//remove::start[]
		this.mockMvc.perform(MockMvcRequestBuilders.post("/beer")
				.contentType(MediaType.APPLICATION_JSON)
				.content(this.json.write(new Person("marcin", 22)).getJson()))
				.andExpect(status().isOk())
				.andExpect(content().string("THERE YOU GO"));
		//remove::end[]
	}

	@Test
	public void should_reject_a_beer_when_im_too_young() throws Exception {
		//remove::start[]
		this.mockMvc.perform(MockMvcRequestBuilders.post("/beer")
				.contentType(MediaType.APPLICATION_JSON)
				.content(this.json.write(new Person("marcin", 17)).getJson()))
				.andExpect(status().isOk())
				.andExpect(content().string("GET LOST"));
		//remove::end[]
	}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_adding_spring_cloud_contract_dependency">Adding Spring Cloud Contract Dependency</h3>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-xml" data-lang="xml">&lt;dependency&gt;
	&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
	&lt;artifactId&gt;spring-cloud-starter-contract-verifier&lt;/artifactId&gt;
	&lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">testCompile("org.springframework.cloud:spring-cloud-starter-contract-verifier")</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_proposal_of_simple_contracts_by_consumer">Proposal of simple contracts by consumer</h3>
<div class="paragraph">
<p><strong>HTTP communication</strong></p>
</div>
<div class="listingblock primary">
<div class="title">Old Enough</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// rest/shouldGrantABeerIfOldEnough.groovy
org.springframework.cloud.contract.spec.Contract.make {
		description("""
Represents a successful scenario of getting a beer

```
given:
	client is old enough
when:
	he applies for a beer
then:
	we'll grant him the beer
```

""")
	request {
		method 'POST'
		url '/check'
		body(
				age: 22,
				name: "marcin"
		)
		headers {
			contentType(applicationJson())
		}
	}
	response {
		status 200
		body("""
			{
				"status": "OK"
			}
			""")
		headers {
			contentType(applicationJson())
		}
	}
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Too Young</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// rest/shouldRejectABeerIfTooYoung.groovy
org.springframework.cloud.contract.spec.Contract.make {
		description("""
Represents a successful scenario of getting a beer

```
given:
	client is old enough
when:
	he applies for a beer
then:
	we'll grant him the beer
```

""")
	request {
		method 'POST'
		url '/check'
		body(
				age: 17,
				name: "marcin"
		)
		headers {
			contentType(applicationJson())
		}
	}
	response {
		status 200
		body("""
			{
				"status": "NOT_OK"
			}
			""")
		headers {
			contentType(applicationJson())
		}
	}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p><strong>Messaging communication</strong></p>
</div>
<div class="listingblock primary">
<div class="title">Positive Verification</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// messaging/shouldSendAcceptedVerification.groovy
org.springframework.cloud.contract.spec.Contract.make {
	description("""
Sends a positive verification message when person is eligible to get the beer

```
given:
	client is old enough
when:
	he applies for a beer
then:
	we'll send a message with a positive verification
```

""")
	// Label by means of which the output message can be triggered
	label 'accepted_verification'
	// output message of the contract
	outputMessage {
		// destination to which the output message will be sent
		sentTo 'verifications'
		// the body of the output message
		body(
            eligible: true
		)
		headers {
			header("contentType", applicationJsonUtf8())
		}
	}
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Negative Verification</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// messaging/shouldSendRejectedVerification.groovy
org.springframework.cloud.contract.spec.Contract.make {
	description("""
Sends a negative verification message when person is not eligible to get the beer

```
given:
	client is too young
when:
	he applies for a beer
then:
	we'll send a message with a negative verification
```

""")
	// Label by means of which the output message can be triggered
	label 'rejected_verification'
	// output message of the contract
	outputMessage {
		// destination to which the output message will be sent
		sentTo 'verifications'
		// the body of the output message
		body(
            eligible: false
		)
		headers {
			header("contentType", applicationJsonUtf8())
		}
	}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_missing_consumer_controller_code">Missing consumer controller code</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">		ResponseEntity&lt;Response&gt; response = this.restTemplate.exchange(
				RequestEntity
						.post(URI.create("http://localhost:" + this.port + "/check"))
						.contentType(MediaType.APPLICATION_JSON)
						.body(person),
				Response.class);
		switch (response.getBody().status) {
		case OK:
			return "THERE YOU GO";
		default:
			return "GET LOST";
		}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_stub_logs">Stub Logs</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">2017-05-11 12:16:51.146  INFO 4693 --- [           main] o.s.c.c.s.StubDownloaderBuilderProvider  : Will download stubs using Aether
2017-05-11 12:16:51.148  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Remote repos not passed but the switch to work offline was set. Stubs will be used from your local Maven repository.
2017-05-11 12:16:51.291  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Desired version is [+] - will try to resolve the latest version
2017-05-11 12:16:51.308  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Resolved version is [0.0.1-SNAPSHOT]
2017-05-11 12:16:51.309  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Resolving artifact [com.example:{producer_artifact}:jar:stubs:0.0.1-SNAPSHOT] using remote repositories []
2017-05-11 12:16:51.317  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Resolved artifact [com.example:{producer_artifact}:jar:stubs:0.0.1-SNAPSHOT] to /home/marcin/.m2/repository/com/example/{producer_artifact}/0.0.1-SNAPSHOT/{producer_artifact}-0.0.1-SNAPSHOT-stubs.jar
2017-05-11 12:16:51.322  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Unpacking stub from JAR [URI: file:/home/marcin/.m2/repository/com/example/{producer_artifact}/0.0.1-SNAPSHOT/{producer_artifact}-0.0.1-SNAPSHOT-stubs.jar]
2017-05-11 12:16:51.327  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Unpacked file to [/tmp/contracts9053257535983128167]
2017-05-11 12:16:52.608  INFO 4693 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@699e0bf0: startup date [Thu May 11 12:16:52 CEST 2017]; root of context hierarchy
2017-05-11 12:16:52.684  INFO 4693 --- [           main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
2017-05-11 12:16:52.837  INFO 4693 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8090 (http)
2017-05-11 12:16:52.851  INFO 4693 --- [           main] o.apache.catalina.core.StandardService   : Starting service Tomcat
2017-05-11 12:16:52.853  INFO 4693 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.14
2017-05-11 12:16:52.975  INFO 4693 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2017-05-11 12:16:52.975  INFO 4693 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 367 ms
2017-05-11 12:16:52.996  INFO 4693 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'stub' to [/]
2017-05-11 12:16:53.000  INFO 4693 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'admin' to [/__admin/*]
2017-05-11 12:16:53.135  INFO 4693 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8090 (http)
2017-05-11 12:16:53.139  INFO 4693 --- [           main] o.s.c.contract.stubrunner.StubServer     : Started stub server for project [com.example:{producer_artifact}:0.0.1-SNAPSHOT:stubs] on port 8090</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_beer_request">Beer Request</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">class BeerRequest {
	public int age;

	public BeerRequest(int age) {
		this.age = age;
	}

	public BeerRequest() {
	}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_missing_listener_code">Missing listener code</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">		if (verification.eligible) {
			this.eligibleCounter.incrementAndGet();
		} else {
			this.notEligibleCounter.incrementAndGet();
		}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_missing_triggers">Missing triggers</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">	@Test public void should_increase_the_eligible_counter_when_verification_was_accepted() throws Exception {
		int initialCounter = this.listener.eligibleCounter.get();

		//remove::start[]
		this.stubTrigger.trigger("accepted_verification");
		//remove::end[]

		then(this.listener.eligibleCounter.get()).isGreaterThan(initialCounter);
	}

	@Test public void should_increase_the_noteligible_counter_when_verification_was_rejected() throws Exception {
		int initialCounter = this.listener.notEligibleCounter.get();

		//remove::start[]
		this.stubTrigger.trigger("rejected_verification");
		//remove::end[]

		then(this.listener.notEligibleCounter.get()).isGreaterThan(initialCounter);
	}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_messaging_dsls">Messaging DSLs</h3>
<div class="listingblock primary">
<div class="title">Positive Verification</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// messaging/shouldSendAcceptedVerification.groovy
org.springframework.cloud.contract.spec.Contract.make {
	description("""
Sends a positive verification message when person is eligible to get the beer

```
given:
	client is old enough
when:
	he applies for a beer
then:
	we'll send a message with a positive verification
```

""")
	// Label by means of which the output message can be triggered
	label 'accepted_verification'
	// input to the contract
	input {
		// the contract will be triggered by a method
		triggeredBy('clientIsOldEnough()')
	}
	// output message of the contract
	outputMessage {
		// destination to which the output message will be sent
		sentTo 'verifications'
		// the body of the output message
		body(
            eligible: true
		)
		headers {
			header("contentType", applicationJsonUtf8())
		}
	}
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Negative Verification</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// messaging/shouldSendRejectedVerification.groovy
org.springframework.cloud.contract.spec.Contract.make {
	description("""
Sends a negative verification message when person is not eligible to get the beer

```
given:
	client is too young
when:
	he applies for a beer
then:
	we'll send a message with a negative verification
```

""")
	// Label by means of which the output message can be triggered
	label 'rejected_verification'
	// input to the contract
	input {
		// the contract will be triggered by a method
		triggeredBy('clientIsTooYoung()')
	}
	// output message of the contract
	outputMessage {
		// destination to which the output message will be sent
		sentTo 'verifications'
		// the body of the output message
		body(
            eligible: false
		)
		headers {
			header("contentType", applicationJsonUtf8())
		}
	}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_producercontroller_implementation">ProducerController implementation</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">if (personCheckingService.shouldGetBeer(personToCheck)) {
    return new Response(BeerCheckStatus.OK);
}
return new Response(BeerCheckStatus.NOT_OK);</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_beerrestbase">BeerRestBase</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@RunWith(MockitoJUnitRunner.class)
public abstract class BeerRestBase {
	@Mock PersonCheckingService personCheckingService;
	@InjectMocks ProducerController producerController;

	@Before
	public void setup() {
		given(personCheckingService.shouldGetBeer(argThat(oldEnough()))).willReturn(true);
		RestAssuredMockMvc.standaloneSetup(producerController);
	}

	private TypeSafeMatcher&lt;PersonToCheck&gt; oldEnough() {
		return new TypeSafeMatcher&lt;PersonToCheck&gt;() {
			@Override protected boolean matchesSafely(PersonToCheck personToCheck) {
				return personToCheck.age &gt;= 20;
			}

			@Override public void describeTo(Description description) {

			}
		};
	}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_beermessagingbase">BeerMessagingBase</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@RunWith(SpringRunner.class)
@SpringBootTest(classes = ProducerApplication.class, webEnvironment = SpringBootTest.WebEnvironment.NONE)
@AutoConfigureMessageVerifier
public abstract class BeerMessagingBase {
	@Inject MessageVerifier messaging;
	@Autowired PersonCheckingService personCheckingService;

	@Before
	public void setup() {
		// let's clear any remaining messages
		// output == destination or channel name
		this.messaging.receive("output", 100, TimeUnit.MILLISECONDS);
	}

	public void clientIsOldEnough() {
		personCheckingService.shouldGetBeer(new PersonToCheck(25));
	}

	public void clientIsTooYoung() {
		personCheckingService.shouldGetBeer(new PersonToCheck(5));
	}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_messaging_implementation">Messaging implementation</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">		boolean shouldGetBeer = personToCheck.age &gt;= 20;
		this.source.output().send(MessageBuilder.withPayload(new Verification(shouldGetBeer)).build());
		return shouldGetBeer;</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_foo_consumer_contracts">Foo-consumer contracts</h3>
<div class="listingblock primary">
<div class="title">Successful</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
Represents a successful scenario of getting a beer

```
given:
	client is old enough
when:
	he applies for a beer
then:
	we'll grant him the beer
```
    """)
    request {
        method POST()
        url "/check"
        body(
                age: $(regex("[2-9][0-9]")),
                name: $(anyAlphaUnicode())
            )
        headers {
            contentType(applicationJson())
        }
    }
    response {
        status 200
        body("""
            {
                "status" : "OK",
                "name": "${fromRequest().body('$.name')}"
            }
        """)
        headers {
            contentType(applicationJson())
        }
    }
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Unsuccessful</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
Represents an unsuccessful scenario of getting a beer

```
given:
	client is too young
when:
	he applies for a beer
then:
	we'll NOT grant him the beer
```
    """)
    request {
        method POST()
        url "/check"
        body(
                age: $(regex("[0-1][0-9]")),
                name: $(anyAlphaUnicode())
            )
        headers {
            contentType(applicationJson())
        }
    }
    response {
        status 200
        body("""
            {
                "status" : "NOT_OK",
                "name": "${fromRequest().body('$.name')}"
            }
        """)
        headers {
            contentType(applicationJson())
        }
    }
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_bar_consumer_contracts">Bar-consumer contracts</h3>
<div class="listingblock primary">
<div class="title">Successful</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
Represents a successful scenario of getting a beer

```
given:
	client is old enough
when:
	he applies for a beer
then:
	we'll grant him the beer
```
    """)
    request {
        method POST()
        url "/check"
        body(
                age: $(regex("[2-9][0-9]")),
                name: $(anyAlphaUnicode())
            )
        headers {
            contentType(applicationJson())
        }
    }
    response {
        status 200
        body("""
            {
                "status" : "OK",
                "surname": "${fromRequest().body('$.name')}"
            }
        """)
        headers {
            contentType(applicationJson())
        }
    }
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Unsuccessful</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
Represents an unsuccessful scenario of getting a beer

```
given:
	client is too young
when:
	he applies for a beer
then:
	we'll NOT grant him the beer
```
    """)
    request {
        method POST()
        url "/check"
        body(
                age: $(regex("[0-1][0-9]")),
                name: $(anyAlphaUnicode())
            )
        headers {
            contentType(applicationJson())
        }
    }
    response {
        status 200
        body("""
            {
                "status" : "NOT_OK",
                "surname": "${fromRequest().body('$.name')}"
            }
        """)
        headers {
            contentType(applicationJson())
        }
    }
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_stubs_per_consumer_beercontroller">Stubs Per Consumer BeerController</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">		ResponseEntity&lt;Response&gt; response = this.restTemplate.exchange(
				RequestEntity
						.post(URI.create("http://localhost:" + this.port + "/check"))
						.contentType(MediaType.APPLICATION_JSON)
						.body(person),
				Response.class);
		switch (response.getBody().status) {
		case OK:
			return "THERE YOU GO " + message(response.getBody());
		default:
			return "GET LOST " + message(response.getBody());
		}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_producercontroller_for_stubs_per_consumer_implementation">ProducerController for stubs per consumer implementation</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">if (personCheckingService.shouldGetBeer(personToCheck)) {
    return new Response(BeerCheckStatus.OK, personToCheck.name);
}
return new Response(BeerCheckStatus.NOT_OK, personToCheck.name);</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_back_to_the_main_page">Back to the Main Page</h2>
<div class="sectionbody">
<div class="paragraph">
<p><a href="../workshops.html">Click here to go back to the main page</a></p>
</div>
</div>
</div>
</div>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.js"></script>
<script>prettyPrint()</script>
</body>
</html>